﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Drawing.Design;
using System.Security;
using System.Security.Permissions;
using System.Windows.Forms.Design;
using System.ComponentModel.Design;
using System.Reflection;
using EnvDTE;
using System.Runtime.InteropServices;
using System.Reflection.Emit;
using EnvDTE80;
using System.IO;
using System.Windows.Forms;
using System.Data.Linq;

namespace Srvtools
{
    public partial class LinqCommand : InfoBaseComp, ILinqCommand
    {
        private string _entityTypeName;

        private string _dataContextTypeName;

        private KeyItems _KeyFields = null;

        public KeyItems KeyFields
        {
            get
            {
                return _KeyFields;
            }
            set
            {
                _KeyFields = value;
            }
        }

        [Editor(typeof(EntityTypeNameEditor), typeof(UITypeEditor))]
        public string EntityTypeName
        {
            get
            {
                return _entityTypeName;
            }
            set
            {
                _entityTypeName = value;
            }
        }

        [Editor(typeof(DataContextTypeNameEditor), typeof(UITypeEditor))]
        public string DataContextTypeName
        {
            get
            {
                return _dataContextTypeName;
            }
            set
            {
                _dataContextTypeName = value;
            }
        }

        public LinqCommand()
        {
            InitializeComponent();
        }

        public LinqCommand(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
        }

        private class DataContextTypeNameEditor : UITypeEditor
        {
            [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
            public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
            {
                return UITypeEditorEditStyle.DropDown;
            }

            [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
            public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
            {
                IWindowsFormsEditorService service = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

                Project project = EditionDifference.ActiveWindow().Project;
                Configuration config = project.ConfigurationManager.ActiveConfiguration;
                DirectoryInfo dictInfo = (new DirectoryInfo(project.FullName)).Parent;

                string fileName = string.Empty;

                foreach (Property prop in config.Properties)
                {
                    if (prop.Name == "OutputPath")      // OutputFileName
                    {
                        fileName += prop.Value.ToString();
                    }
                }

                foreach (Property prop in project.Properties)
                {
                    if (prop.Name == "OutputFileName")      // OutputFileName
                    {
                        fileName += prop.Value.ToString();
                    }
                }

                string[] ss = fileName.Split(@"\".ToCharArray());
                foreach (string s in ss)
                {
                    if (s == "..") dictInfo = dictInfo.Parent;
                }

                fileName = dictInfo.FullName + @"\" + fileName.Replace("..", "");

                if (!File.Exists(fileName))
                {
                    MessageBox.Show("Please first build this project.");
                    return null;
                }

                FileInfo fileInfo = new FileInfo(fileName);

                AppDomainSetup setup = new AppDomainSetup();
                setup.ApplicationBase = fileInfo.DirectoryName;
                setup.ShadowCopyDirectories = fileInfo.DirectoryName;
                setup.PrivateBinPath = fileInfo.DirectoryName;
                setup.ApplicationName = "LinqCommand_ChooseDataContextTypeName";
                setup.ShadowCopyFiles = "true";

                AppDomain appDomain = AppDomain.CreateDomain(fileName, null, setup);

                Assembly assembly = appDomain.Load(AssemblyName.GetAssemblyName(fileName));

                List<string> list = new List<string>();
                Type[] types = assembly.GetTypes();
                foreach (Type type in types)
                {
                    if (type.IsSubclassOf(typeof(DataContext)))
                    {
                        list.Add(string.Format("{0}.{1}", type.Namespace, type.Name));
                    }
                }

                if (service != null)
                {
                    StringListSelector slector = new StringListSelector(service, list.ToArray());
                    string strValue = (string)value;
                    if (slector.Execute(ref strValue)) value = strValue;
                }

                AppDomain.Unload(appDomain);

                return value;
            }
        }

        private class EntityTypeNameEditor : UITypeEditor
        {
            [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
            public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
            {
                return UITypeEditorEditStyle.DropDown;
            }

            [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
            public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
            {
                IWindowsFormsEditorService service = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

                Project project = EditionDifference.ActiveWindow().Project;
                Configuration config = project.ConfigurationManager.ActiveConfiguration;
                DirectoryInfo dictInfo = (new DirectoryInfo(project.FullName)).Parent;

                string fileName = string.Empty;

                foreach (Property prop in config.Properties)
                {
                    if (prop.Name == "OutputPath")      // OutputFileName
                    {
                        fileName += prop.Value.ToString();
                    }
                }

                foreach (Property prop in project.Properties)
                {
                    if (prop.Name == "OutputFileName")      // OutputFileName
                    {
                        fileName += prop.Value.ToString();
                    }
                }

                string[] ss = fileName.Split(@"\".ToCharArray());
                foreach (string s in ss)
                {
                    if (s == "..") dictInfo = dictInfo.Parent;
                }

                fileName = dictInfo.FullName + @"\" + fileName.Replace("..", "");

                if (!File.Exists(fileName))
                {
                    MessageBox.Show("Please first build this project.");
                    return null;
                }

                FileInfo fileInfo = new FileInfo(fileName);

                AppDomainSetup setup = new AppDomainSetup();
                setup.ApplicationBase = fileInfo.DirectoryName;
                setup.ShadowCopyDirectories = fileInfo.DirectoryName;
                setup.PrivateBinPath = fileInfo.DirectoryName;
                setup.ApplicationName = "LinqCommand_ChooseDataContextTypeName";
                setup.ShadowCopyFiles = "true";

                AppDomain appDomain = AppDomain.CreateDomain(fileName, null, setup);

                Assembly assembly = appDomain.Load(AssemblyName.GetAssemblyName(fileName));

                List<string> list = new List<string>();
                Type[] types = assembly.GetTypes();
                foreach (Type type in types)
                {
                    if (type.GetInterface("INotifyPropertyChanging") != null)
                    {
                        list.Add(string.Format("{0}.{1}", type.Namespace, type.Name));
                    }
                }

                if (service != null)
                {
                    StringListSelector slector = new StringListSelector(service, list.ToArray());
                    string strValue = (string)value;
                    if (slector.Execute(ref strValue)) value = strValue;
                }

                AppDomain.Unload(appDomain);

                return value;
            }
        }
    }
}
